//
// Created by Sugars Mac on 2020/5/26.
//

#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include "relation.h"

// 查找空聊天室的下标
int searchEmptyRoom(room_t* rooms, int size){ // size一般是MAXMEM
    int i;
    for(i = 0; i < size; i++){
        if (rooms[i].roomname == NULL && rooms[i].roompass == NULL){
            return i;
        }
    }
    return -1;
}

int findRoomByName(room_t* rooms, int size, char* name){
    int i;
    for (i = 0; i < size; ++i) {
        if (rooms[i].roomname != NULL && strcmp(rooms[i].roomname, name) == 0) {
            return i;
        }
    }
    return -1; // 未找到有关房间
}

// 文件有关操作
int readFromFile(TableList_t* head) {
    printf("loading user's information...\n");
    int fd = open("user.dat", O_RDONLY);

    UserTable_t * buf;

    int size = 1;
    while (size){
        buf = (UserTable_t*)malloc(sizeof(UserTable_t));
        size = read(fd, buf, sizeof(UserTable_t));
        if (-1 == size){
            close(fd);
            printf("read file error occurs\n");
            return false;
        } else {
            if(size > 0){
//                printf("read %d bytes:", size);
//                printf("username: %s, password: %s\n", buf->username, buf->password);
                insertTable(head, buf);
                buf = NULL;
            } else {
                printf("finish read.\n");
            }
        }
    }
    return true;
}

int writeToFile(TableList_t* head){
    int fd;
    TableList_t * ptr = NULL;

    fd = open("user.dat", O_WRONLY);

    ptr = head->next;
    while (ptr) {
        write(fd, ptr->data, sizeof(UserTable_t));
        ptr = ptr->next;
    }

    close(fd);
    return true;
}
// 新增注册用户
int insertTable(TableList_t* head, UserTable_t * user){
    TableList_t * node = (TableList_t*)malloc(sizeof(TableList_t));
    node->data = user;
    node->next = head->next;
    head->next = node;
    return true;
}

void showTable(TableList_t* head){
    TableList_t * ptr = head->next;
    while (ptr){
        printf("username = %s, password = %s\n", ptr->data->username, ptr->data->password);
        ptr = ptr->next;
    }
}

void destroyTable(TableList_t* head){
    TableList_t * ptr = head->next, *pre;
    while (ptr) {
        pre = ptr;
        ptr = ptr->next;
        free(pre->data);
        free(pre);
    }
    free(head);
}

// 根据用户名查找用户登陆信息
UserTable_t * findUserByName(TableList_t* head, char * username){
    TableList_t * ptr = head->next;
    while (ptr) {
        if(strcmp(ptr->data->username, username) == 0){
            return ptr->data; // 返回用户名和密码
        }
        ptr = ptr->next;
    }
    return NULL;
}

user_t* buildUser(int sockfd, char* name){
    user_t *user = (user_t*)malloc(sizeof(user_t));
    user->sockfd = sockfd;
    // printf("the strlen(name) = %lu\n", strlen(name));
    user->username = malloc(sizeof(char) * (strlen(name)));
    strcpy(user->username, name);
    return user;
}

/**
 * 根据用户socket获取用户所在下标
 * @param users
 * @param len
 * @param sock
 * @return
 */
int findUserIndexBySocket(user_t* users, int len, int sock){
    int i;
    for(i = 0; i < len; i++){
        if(users[i].sockfd == sock){
            return i;
        }
    }
    return -1;
}

int findUserSockByName(user_t* users, int len, char* name){
    int i = 0;
    for(i = 0; i < len; i++){
        if(users[i].sockfd != -1){
            if (users[i].username == NULL){
                continue;
            }
            if(strcmp(name, users[i].username) == 0){
                return users[i].sockfd;
            }
        }
    }
    return -1;  // 未找到该用户则返回-1
}

int compareUser(user_t u1, user_t u2){
    if(strcmp(u1.username, u2.username) == 0){
        if(u1.sockfd == u2.sockfd){
            return 1;
        }
    }
    return 0;
}

int compareRelation(relationMap* r1, relationMap* r2){
    if(r1->sockB == r2->sockB && r1->sockA == r2->sockA){
        return 1;
    }
    if (r1->sockB == r2->sockA && r1->sockA == r2->sockB){
        return 1;
    }
    return 0;
}

relationMap* buildRelation(int u1, int u2){
    relationMap * relation = (relationMap*)malloc(sizeof(relationMap));
    relation->sockA = u1;
    relation->sockB = u2;
    relation->next = NULL;
    return relation;
}

int addRelation(relationMap* head, relationMap* rel){
    if(head->next == NULL){
        head->next = rel;
        return 1;
    } else {
        rel->next = head->next;
        head->next = rel;
        return 1;
    }
}

void showRelation(relationMap* head){
    relationMap * p = head->next;
    while(p){
        printf("%d -> %d\n", p->sockA, p->sockB);
        p = p->next;
    }
}

int deleteRelation(relationMap* head, relationMap* rel){
    relationMap * p = head->next;
    relationMap * pre = head;
    while(p){
        if(compareRelation(p, rel)){ // 找到了要删除的关系
            pre->next = p->next;
            p->next = NULL;
            free(p);
            return 1;
        }
        pre = p;
        p = p->next;
    }
    return 0;
}


int findRelation(relationMap* head, relationMap* rel){
    relationMap * p = head->next;
    while (p){
        if(compareRelation(p, rel)){
            return 1;
        }
        p = p->next;
    }
    return 0; // 不存在该关系
}

void deleteAllRela(relationMap* head){
    relationMap * p = head->next, *tmp = NULL;
    while (p){
        printf("free the %d->%d\n", p->sockA, p->sockB);
        tmp = p->next;
        free(p);
        p = tmp;
    }
}

/**
 * 判断用户是否建立起私聊关系,即判断u是否为私聊建立者
 * @param head ：关系链表
 * @param u ：用户socket
 * @return 如果有则返回该关系，没有则为NULL
 */
relationMap * existRelation(relationMap * head, int u){
    relationMap * p = head->next;
    while (p) {
        if(p->sockA == u){
            return p;
        }
        p = p->next;
    }
    return NULL;
}

/**
 * 判断用户u是否被其他人建立起了私聊关系，即u是否是私聊接受者
 * @param head
 * @param u 用户socket
 * @return
 */
relationMap * beContacted(relationMap * head, int u){
    relationMap * p = head->next;
    while (p) {
        if(p->sockB == u){
            return p;
        }
        p = p->next;
    }
    return NULL;
}

void deleteRelationBySocket(relationMap * head, int u){
    relationMap * p = head->next;
    while (p) {
        if (p->sockB == u) {
            int sockA = p->sockA; // 用于通知对应用户
            deleteRelation(head, p);
            char * buf = "OFFL";
            write(sockA, buf, strlen(buf));
            break;
        } else if (p->sockA == u){
            int sockB = p->sockB;
            deleteRelation(head, p);
            write(sockB, "对方掉线了", 10);
            break;
        }
        p = p->next;
    }
}